

#include "app.h"



void App::print_all_tasks() {
    char task_list_buffer[1024]; // 缓冲区大小建议 >= 512 字节
    vTaskList(task_list_buffer); // 获取任务信息
    printf("Task List:\n%s\n", task_list_buffer);
} 


App::App(){
    work_task_      = new WorkTask(4096*8);
    opus_encoder_   = std::make_unique<OpusEncoderWrapper>(16000, 1, 60);
    audio_input_    = std::make_unique<AudioEs7210>(16000, 1);
    file_           = std::make_unique<SdCard>(); 
    opus_decoder_   = std::make_unique<OpusDecoderWrapper>(16000,1,60);
}

App::~App(){

}

void App::run(){ 
    // //打开文件
    // ESP_ERROR_CHECK(file_->open("test.opus","wb")); 
    std::printf("开始说话\n");
    //启动录音
    audio_input_->enable();
    vTaskDelay(pdMS_TO_TICKS(1000));    

    //录音50帧，每帧60ms,总共3秒
    for (size_t i = 0; i < 50; i++)
    {
        // 创建动态数组，用于存储录音数据（频繁在堆内存分配空间造成内存碎片）
        std::vector<int16_t> pcm(960);
        // 读取录音数据(注意这里面传入的读取数据大小是字节数，所以要*sizeof(int16_t))
        audio_input_->read(pcm.data(), pcm.size()*sizeof(int16_t), nullptr);

        // 提交任务到后台线程执行，用于编码
        work_task_->enqueue_task([this,pcm = std::move(pcm)]() mutable {  
            
            opus_encoder_->Encode(std::move(pcm),[this](std::vector<uint8_t>&& opus){ 
                // 存放到内存中
                // 直接保存Opus数据包（不需要帧长度头）
                opus_packets_.emplace_back(std::move(opus));

                // 存放到SD卡中
                // // 1. 计算帧长度（4字节大端序）
                // uint32_t frame_size = static_cast<uint32_t>(opus.size());
                // // 2、转为大端序
                // uint32_t frame_size_big_endian = htonl(frame_size); // 转为大端序

                // // 3. 先写入帧长度（4字节）
                // file_->write_file(reinterpret_cast<const char*>(&frame_size_big_endian), sizeof(frame_size_big_endian));

                // // 4. 再写入编码后的数据
                // file_->write_file(reinterpret_cast<const char*>(opus.data()), opus.size());
                
            });
        });
    }
    //延时（必要，等待后台任务执行完成），否则关闭文件可能会失败，因为后台任务还在执行，其在执行过程中会不断往文件中写入数据
    vTaskDelay(pdMS_TO_TICKS(1000));    
    audio_input_->disable();
    std::printf("结束说话\n");
    // file_->close();

    for (auto& opus : opus_packets_) {
        // mutable 引用，用于修改 lambda 表达式中被捕获的变量
        work_task_->enqueue_task([this,opus = std::move(opus)]() mutable{
            std::vector<int16_t> decoded_pcm; 
            opus_decoder_->Decode(std::move(opus), decoded_pcm); 
        });  
    }


    while (true)
    {
        vTaskDelay(pdMS_TO_TICKS(1000));    
        print_all_tasks();     
    }
}